Explicit specializations of function templates are not considered in overload resolution, only the main template. As a consequence, the function
that will be selected might very well be different from what seems natural to the developer, leading to hard to understand bugs. Moreover, function
templates don’t allow partial specialization.
Instead of specializing a function template, you may choose to overload it with another template or non template function, since a more specialized
overload will be preferred to a generic overload.
Noncompliant code example
template <typename T> void f ( T );
template <> void f<char*> ( char * ); // explicit specialization, noncompliant
Compliant solution
template <typename T> void f ( T );
void f( char * ); // overload, compliant
Exceptions
This rule ignores cases where none of the main function template arguments depend on a template parameter: Even if the code could still be written
without function template specialization (by deferring the real work to a class template, and offering specializations of this class template as
customization point to the user), there is no risk of confusion for overload resolution in these cases.
// For real code, use std::numeric_limits instead...
template <class T> T max();
template <> float max<float>() { return FLT_MAX; } // Ignored
template<class T>
bool isMax(T t){
return t == max<T>();
}